import axios from 'axios';
import { Message, Notification } from 'element-ui';
import deepClone from '@/utils/clone';
import { parseStr2Date, selectDictLabel } from '@/utils/microsys';
import { compare } from '@/utils/util';
import ReconnectingWebSocket from 'reconnecting-websocket';

import { suppliesTypePage, suppliesPage } from '@/api/supplies';
import { getAreaList, getEquipmentList, getPartList } from '@/api/warning';
import { eventPage } from '@/api/event';
var lockReconnect = false; //避免重复连接
var lockReconnectNum = 0; //重复连接次数
const cache = {
  state: {
    operatorInfo: null, // 操作员信息
    operatorCallTels: null, // 操作员主叫号码
    handMicphone: null,

    nid: 0, // 树结构节点id
    id2nidMap: new Map(), // 用户id和树结构nid
    gpsBHMap: new Map(), // gps编号

    videoTreeData: [], // 视频和组数据
    videoGroupTreeData: [], // 视频组数据，只包含组数据
    videoGroupMap: new Map(),
    videoMap: new Map(),

    userTreeData: [], // 用户和组数据
    userGroupTreeData: [], // 用户组数据，只包含组数据
    userGroupTreeDataAll: [], // 用户组数据，只包含组数据(处理动态编组数据被过滤)
    userTreeDataToDepart: [], // 用户和组数据(号码分成多个)
    userDynamicGroupTreeData: [], // 动态编组和宽带集群

    groupMap: new Map(),
    copyGroupMap: new Map(),
    operatorMap: new Map(),
    telOperatorMap: new Map(),
    employeeMap: new Map(),
    telEmployeeMap: new Map(),
    bindingVideoMap: new Map(),
    telMeetingMap: new Map(), //号码所处会议id

    videoNidMap: new Map(),

    faxTelTreeData: [],
    faxTelMap: new Map(),

    deviceStatusMap: new Map(),
    deviceLinkMap: new Map(),

    // 物资
    hasSuppliesModule: false, // 是否有物资模块
    suppliesTypeList: [],
    suppliesTypeMap: new Map(),
    suppliesList: [],
    suppliesMap: new Map(),
    suppliesTreeData: [],
    warningNotificationMap: new Map(), // 告警信息通知

    associatedMap: new Map(), // 物资关联映射表(暂只包含摄像头)

    hasEventModule: false, // 是否有事件模块
    eventList: [], // 事件
    eventTreeData: [],
    eventMap: new Map(), // 事件
    eventTypeMap: new Map(),

    hasWarningModule: false, // 是否有告警模块
    warningTreeData: [],
    warningAreaMap: new Map(), // 告警区域
    warningEquipmentMap: new Map(), // 告警设备
    warningEquipmentPartMap: new Map(), // 告警设备通道

    websocketClient: null, //事件和物资上报
    websocketTimer: null, //事件和物资上报定时器
    websocketCallback: null, // 回调事件

    //菜单key
    navKey: 1,
    menuList: [],
    //
    websocketLocalClient: null, //摘挂机事件上报
    localWebSocketFlag: false,
    localPhoneStatus: '',
    localButtonStatus: '',
    callFlag: false, //主动拨打状态
    powerStatus: false, // 抢权状态

    centerAndZoom: {}, // 地图缩放等级和中心点

    msgIdMap: new Map(), // 存储修改id

    // gis地图视频播放数据
    gis_video_play_data: null,
    //语音会议联动视频播放数据
    meet_linked_video_play_data: null,

    // 电子围栏告警提示框
    fenceAlarmMap: new Map(),
  },

  mutations: {
    // 设置地图视频播放数据
    GisPlayData(state, data) {
      if (data) {
        state.gis_video_play_data = data;
        sessionStorage.setItem('gis_video_play_data', JSON.stringify(data));
      } else {
        state.gis_video_play_data = null;
        sessionStorage.removeItem('gis_video_play_data');
      }
    },
    // 设置语音会议视频播放数据
    MeetPlayData(state, data) {
      if (data) {
        state.meet_linked_video_play_data = data;
        sessionStorage.setItem(
          'meet_linked_video_play_data',
          JSON.stringify(data)
        );
      } else {
        state.meet_linked_video_play_data = null;
        sessionStorage.removeItem('meet_linked_video_play_data');
      }
    },
    // 关闭关联摄像头
    LinkVideoClose(state, e) {
      console.log('cache 关闭关联摄像头', e);

      const closeVideo = (data, videoID, type) => {
        if (!data) return;
        let playList = data.playList;
        let index = playList.findIndex(item => item.videoID === videoID);
        if (index !== -1) {
          let playObj = playList[index];
          if (!playObj || Object.keys(playObj).length === 0) return;

          if (playObj.rtspNode) {
            clearInterval(playObj.rtspNode.Interval);
            playObj.rtspNode.PC.close();
            if (playObj.flowID) SDK.closeVideo(playObj.videoID, playObj.flowID);
          }
          playList[index] = {};
        }

        // 退出分发
        let old = sessionStorage.getItem(`dispense-${videoID}`);
        if (old) {
          let datas = JSON.parse(old);
          datas.forEach(item => {
            SDK.stopVideoDispense({
              flowID: item.flowID,
              videoID,
            });
          });
          sessionStorage.removeItem(`dispense-${videoID}`);
        }

        let camaras = data.camaras;
        if (camaras.length < 2) {
          type === 'gis'
            ? this.commit('GisPlayData', null)
            : this.commit('MeetPlayData', null);
        } else {
          let idx = camaras.findIndex(c => c.id === videoID);
          if (idx !== -1) {
            camaras.splice(idx, 1);
            type === 'gis'
              ? this.commit('GisPlayData', data)
              : this.commit('MeetPlayData', data);
          }
        }
      };

      closeVideo(state.gis_video_play_data, e.videoID, 'gis');
      closeVideo(state.meet_linked_video_play_data, e.videoID, 'meet');
    },
    // 设置操作员信息
    SetOperatorInfo(state, operatorInfo) {
      if (operatorInfo) {
        state.operatorInfo = operatorInfo;
        this.commit('OperatorCallTes');
      } else if (!state.operatorInfo) {
        state.operatorInfo = {};
        SDK.operatorquery().then(res => {
          console.log('SetOperatorInfo', res);
          state.operatorInfo = res.eventdata;
          this.commit('OperatorCallTes');
        });
      }
    },
    // 初始化操作员主叫号码
    OperatorCallTes(state) {
      let operatorInfo = state.operatorInfo;
      let callings = [];
      let handMicphone;
      if (operatorInfo.mainTel) {
        if (operatorInfo.mainTelType === 'phone')
          callings.push(operatorInfo.mainTel);
        else handMicphone = operatorInfo.mainTel;
      }
      if (operatorInfo.viceTel) {
        if (operatorInfo.viceTelType === 'phone')
          callings.push(operatorInfo.viceTel);
        else if (!handMicphone) handMicphone = operatorInfo.viceTel;
      }
      state.operatorCallTels = callings.length > 0 ? callings : null;
      state.handMicphone = handMicphone;
    },
    // 获取节点id, 用来保证数据节点id唯一
    GetNid(state, node) {
      state.nid++;
      node.nid = state.nid;
    },
    // 设置用户id和树nid的对应关系
    SetId2Nid(state, { id, nid }) {
      let val = state.id2nidMap.get(id);
      if (val) {
        val.push(nid);
        return;
      }
      state.id2nidMap.set(id, [nid]);
    },
    // 设置默认中心点和缩放等级
    SetCenterAndZoom(state, centerAndZoom) {
      if (centerAndZoom) {
        state.centerAndZoom = centerAndZoom;
        sessionStorage.setItem(
          'gis-center-zoom',
          JSON.stringify(centerAndZoom)
        );
        return;
      }
      state.centerAndZoom = sessionStorage.getItem('gis-center-zoom')
        ? JSON.parse(sessionStorage.getItem('gis-center-zoom'))
        : bmapConfig.centerAndZoom;
    },
    //主动拨打状态变更事件
    callFlagEvent(state, type) {
      console.log('callFlagEvent', status);
      state.callFlag = type;
    },
    setPowerStatus(state, status) {
      console.log('setPowerStatus', status);
      state.powerStatus = status;
    },
    // websocket回调
    setWebsocketCallback(state, callback) {
      state.websocketCallback = callback;
    },
    updateSuppliesForPos(state, { suppliesId, pos_x, pos_y }) {
      const supplies = state.suppliesMap.get(suppliesId);
      if (supplies) {
        supplies.pos_x = pos_x;
        supplies.pos_y = pos_y;
      }
    },
    updateSupplies(state, { suppliesId, data, obj }) {
      const supplies = state.suppliesMap.get(suppliesId);
      console.log('updateSupplies', JSON.stringify({ suppliesId, data, obj }));
      let status = -1; //0新增 1更新 2删除
      if (supplies) {
        if (obj) {
          obj.pos_x = obj.eventLongitude || '';
          obj.pos_y = obj.eventLatitude || '';
          state.suppliesMap.delete(suppliesId);
          state.suppliesMap.set(suppliesId, obj);
          status = 1;
        } else if (data.realInfo) {
          // 实时信息上报
          let realInfo = JSON.parse(data.realInfo);
          // console.log('updateSupplies', JSON.stringify(realInfo));
          supplies.realInfo = realInfo;
          let typeObj = state.suppliesTypeMap.get(supplies.typeId);
          if (typeObj && typeObj.obj.typeNum === 'sensor') {
          } else {
            console.log('定位信息上报');
            // 定位信息上报
            supplies.pos_x = realInfo.longitude;
            supplies.pos_y = realInfo.latitude;
          }
        }
        if (state.websocketCallback) {
          state.websocketCallback(supplies, status);
        }
      }
    },
    //事件上报处理
    updateEvent(state, { data, eventTypeOptions }) {
      if (!state.eventTypeMap || state.eventTypeMap.size === 0) {
        console.log('数据没有加载完成');
        return;
      }

      let obj = data.data;
      let event = state.eventMap.get(obj.eventId);
      let status = 0; //0新增 1更新 2删除

      obj.pos_x = obj.eventLongitude || '';
      obj.pos_y = obj.eventLatitude || '';

      if (event) {
        let index = state.eventList.findIndex(
          item => item.eventId === obj.eventId
        );
        let pnode = state.eventTypeMap.get(event.eventType);
        if (pnode) {
          let childIndex = pnode.children.findIndex(
            item => item.id === obj.eventId
          );
          if (childIndex !== -1) {
            pnode.children.splice(childIndex, 1);
          }
        }
        if (index !== -1) state.eventList.splice(index, 1);

        if (obj.isValid === 0 || obj.eventStatus === 3) {
          // 删除或者已处理完成
          if (index !== -1) {
            state.eventMap.delete(obj.eventId);
          }
          status = 2;
        } else {
          status = 1;
        }
      }
      if (status !== 2) {
        state.eventList.push(obj);
        state.eventMap.set(obj.eventId, obj);
        let node = { obj };
        this.commit('GetNid', node);
        node.label = obj.eventName;
        node.type = 'event';
        node.id = obj.eventId;
        node.parentID = obj.eventType;
        node.isLeaf = true;
        let pnode = state.eventTypeMap.get(obj.eventType);
        if (pnode) {
          pnode.children.push(node);
          this.commit('SetId2Nid', node);
        }
        window.handleCreatEventNotification(obj, eventTypeOptions);
      }
      if (state.websocketCallback) {
        state.websocketCallback(data, status);
      }
    },
    updateLocation(state, pos) {
      const obj = state.gpsBHMap.get(pos.deviceCode);
      if (obj) {
        obj.pos_x = pos.pos_x;
        obj.pos_y = pos.pos_y;
      }
    },
  },

  actions: {
    // 获取数据
    InitCache({ dispatch, commit, state }) {
      state.gpsBHMap = new Map(); // 初始化话gps编号
      dispatch('initUser'); // 初始化用户（组、操作员、职员）
      // dispatch('initVideo'); // 初始化视频组和摄像头
      dispatch('initLocalWebSocket'); //初始化摘挂机信号webscoket
      // dispatch('initSupplies'); // 初始化物资和事件
    },

    //单模块登录连接websocket获取数据
    InitCacheAlone({ dispatch, commit, state }, type) {
      dispatch('initWebsocket', type); // 初始化物资和事件
    },

    initUser({ dispatch, commit, state }) {
      axios
        .all([SDK.group(), SDK.operator({ groupid: 'all' }), SDK.employee()])
        .then(
          axios.spread((groupRes, operRes, empRes) => {
            let node, pNode;
            // 组
            let groupMap = (state.groupMap = new Map());
            let groups = groupRes.data.organizations;
            //排序
            groups.sort(compare('orderNO'));
            // 用Map保存，方便树结构
            groups.forEach(item => {
              node = { obj: item };
              commit('GetNid', node);
              node.label = item.groupName;
              node.type = 'group';
              node.isLeaf = false;
              node.id = item.groupID;
              node.parentID = item.parentID;
              node.children = [];
              groupMap.set(item.groupID, node);

              commit('SetId2Nid', node);
            });

            // 用来保存无子类的纯组数据
            state.copyGroupMap = deepClone(groupMap);
            // 组为空时，树结构数据为空
            if (groupMap.size === 0) {
              state.userTreeData = [];
              return;
            }

            // 树结构
            let treeMap = new Map();
            for (let key of groupMap.keys()) {
              node = groupMap.get(key);
              let pid = node.parentID;
              // if (
              //   node.obj.groupType === 'dynamicgroup' ||
              //   node.obj.groupType === 'clustergroup'
              // ) {
              //   continue;
              // }
              if (pid === '' && !treeMap.has(pid)) {
                treeMap.set(key, node);
              } else if (pid !== '') {
                pNode = groupMap.get(pid);
                if (pNode) pNode.children.push(node);
              }
            }
            //所有组
            state.userGroupTreeDataAll = deepClone([...treeMap.values()]);
            //过滤 集群组、监听组 de
            const obj = fiterUserGroupTreeData(
              deepClone([...treeMap.values()])
            );
            state.userGroupTreeData = obj; // 用户组数据

            // 操作员
            let operators = operRes.data.operator;
            let operatorMap = new Map();
            state.telOperatorMap = new Map();
            if (operators && operators.length > 0) {
              operators.forEach(item => {
                node = { obj: item };
                commit('GetNid', node);
                node.label = item.realName;
                node.type = 'operator';
                node.isLeaf = true;
                node.id = item.operatorID;
                node.parentID = item.groupID;
                pNode = groupMap.get(item.groupID);
                if (pNode) {
                  pNode.children.push(node);

                  commit('SetId2Nid', node);
                }
                operatorMap.set(item.operatorID, item);
                if (item.gpsBH) state.gpsBHMap.set(item.gpsBH, item);

                dispatch('initTelOperator', item);
              });
            }

            state.operatorMap = operatorMap;

            // 职员
            let employees = !empRes.data.employee ? [] : empRes.data.employee;
            let employeeMap = new Map();
            state.telEmployeeMap = new Map();
            let telObj;
            for (let i = 0; i < employees.length; i++) {
              const item = employees[i];
              if (employeeMap.has(item.employeeID)) {
                continue;
              }
              if (!item.videoID) item.videoID = [];

              telObj = item.device.find(
                tel => tel.deviceTel === item.defaultNo
              );
              if (telObj) {
                item.deviceType = telObj.deviceType;
              } else {
                item.defaultNo = item.device[0].deviceTel;
                item.deviceType = item.device[0].deviceType;
              }

              if (item.group.length > 0) {
                item.group.forEach(p => {
                  pNode = groupMap.get(p.groupID);
                  if (pNode) {
                    node = { obj: item };
                    commit('GetNid', node);
                    node.label = item.realName;
                    node.type = 'employee';
                    node.isLeaf = true;
                    node.id = item.employeeID;
                    node.parentID = p.groupID;
                    pNode.children.push(node);

                    commit('SetId2Nid', node);
                  }
                });

                // 添加到Map中
                employeeMap.set(item.employeeID, item);
                if (item.gpsBH) state.gpsBHMap.set(item.gpsBH, item);
              }

              dispatch('initTelEmployee', item);
            }

            state.employeeMap = employeeMap;

            state.userTreeData = [...treeMap.values()];

            dispatch('initDynamic');
            dispatch('initUserStatus'); // 初始化号码状态
            dispatch('initDepartTel', { operators, employees }); // 初始化号码和员工
            dispatch('initBindingVideo', { operators, employees }); // 初始化操作员和职员和摄像头绑定关系
            dispatch('initUserMeeting'); // 初始化会议成员
          })
        )
        .catch(err => {
          console.log('初始化用户数据失败');
          console.log(err);
        });
    },
    initTelOperator({ state }, obj) {
      if (obj.mainTel) {
        state.telOperatorMap.set(obj.mainTel, obj);
      } else if (obj.viceTel) {
        state.telOperatorMap.set(obj.viceTel, obj);
      }
    },
    initTelEmployee({ state }, obj) {
      for (const telObj of obj.device) {
        if (telObj.deviceTel) {
          state.telEmployeeMap.set(telObj.deviceTel, obj);
        }
      }
    },
    initVideo({ dispatch, commit, state }) {
      axios
        .all([SDK.videoGroup(), SDK.video()])
        .then(
          axios.spread((groupRes, videoRes) => {
            let node, pNode;
            // 视频组
            let videoGroupMap = (state.videoGroupMap = new Map());
            let groups = groupRes.data.organizations;
            groups.forEach(item => {
              node = { obj: item };
              commit('GetNid', node);
              node.label = item.groupName;
              node.type = 'videogroup';
              node.isLeaf = false;
              node.id = item.videoGroupID;
              node.parentID = item.parentID;
              node.children = [];
              videoGroupMap.set(item.videoGroupID, node);

              commit('SetId2Nid', node);
            });

            if (videoGroupMap.size === 0) {
              return (state.videoTreeData = []);
            }
            // 树结构
            let treeMap = new Map();
            for (let key of videoGroupMap.keys()) {
              node = videoGroupMap.get(key);
              let pid = node.parentID;
              if (pid === '' && !treeMap.has(pid)) {
                treeMap.set(key, node);
              } else if (pid !== '') {
                pNode = videoGroupMap.get(pid);
                if (pNode) pNode.children.push(node);
              }
            }

            state.videoGroupTreeData = deepClone([...treeMap.values()]); // 视频组数据

            // 摄像头
            let cameras = !videoRes.data.cameras ? [] : videoRes.data.cameras;
            let videoMap = new Map();
            let videoNidMap = (state.videoNidMap = new Map());
            for (let i = 0, length = cameras.length; i < length; i++) {
              let item = cameras[i];
              if (videoMap.has(item.videoID)) {
                continue;
              }
              if (item.group.length > 0) {
                item.group.forEach(p => {
                  pNode = videoGroupMap.get(p.groupID);
                  if (pNode) {
                    node = { obj: item };
                    commit('GetNid', node);
                    node.label = item.videoName;
                    node.type = 'video';
                    node.isLeaf = true;
                    node.id = item.videoID;
                    node.parentID = p.groupID;
                    pNode.children.push(node);

                    commit('SetId2Nid', node);
                    let nids = videoNidMap.get(item.videoID);
                    if (nids) nids.push(node.nid);
                    else videoNidMap.set(item.videoID, [node.nid]);
                  }
                });
                // 添加到Map中
                videoMap.set(item.videoID, item);
                if (item.gpsBH) state.gpsBHMap.set(item.gpsBH, item);
              }
            }
            state.videoMap = videoMap;
            state.videoTreeData = [...treeMap.values()];
          })
        )
        .catch(err => {
          console.log('初始化视频组和摄像头数据失败');
        });
    },
    initDynamic({ dispatch, commit, state }) {
      // 动态编组树结构
      let dynamicTreeMap = new Map();
      let copyMap = deepClone(state.copyGroupMap);

      const dynamic = n => {
        let pid = n.parentID;
        if (pid === '' && !dynamicTreeMap.has(pid)) {
          dynamicTreeMap.set(n.id, n);
        } else if (pid !== '') {
          let pNode = copyMap.get(pid);
          if (pNode) {
            pNode.children.push(n);
            if (pNode.children.length === 1) dynamic(pNode);
          }
        }
      };
      for (let key of copyMap.keys()) {
        let node = copyMap.get(key);
        if (
          node.obj.groupType === 'dynamicgroup' ||
          node.obj.groupType === 'clustergroup'
        ) {
          dynamic(node);
        }
      }

      state.userDynamicGroupTreeData = [...dynamicTreeMap.values()]; // 动态编组和集群组
    },
    initUserStatus({ dispatch, commit, state }) {
      SDK.userStatus().then(res => {
        res.userList.forEach(item => {
          handleUserStatus(state, item);
        });
      });
    },
    initDepartTel({ dispatch, commit, state }, { operators, employees }) {
      const groupMap = deepClone(state.copyGroupMap);
      if (groupMap.size > 0) {
        let node, pNode, pid;
        // 树结构
        let treeMap = new Map();
        for (let key of groupMap.keys()) {
          node = groupMap.get(key);
          if (
            node.obj.groupType === 'dynamicgroup' ||
            node.obj.groupType === 'clustergroup'
          )
            continue;
          pid = node.parentID;
          if (pid === '' && !treeMap.has(pid)) {
            treeMap.set(key, node);
          } else if (pid !== '') {
            pNode = groupMap.get(pid);
            if (pNode) pNode.children.push(node);
          }
        }
        const faxMap = deepClone(state.copyGroupMap); // 传真
        // 树结构
        let faxTreeMap = new Map();
        for (let key of faxMap.keys()) {
          node = faxMap.get(key);
          pid = node.parentID;
          if (pid === '' && !faxTreeMap.has(pid)) {
            faxTreeMap.set(key, node);
          } else {
            pNode = faxMap.get(pid);
            if (pNode) pNode.children.push(node);
          }
        }

        // 操作员
        for (let i = 0; i < operators.length; i++) {
          let obj = operators[i];
          pid = obj.groupID;
          pNode = groupMap.get(pid);
          if (!pNode) continue;
          if (obj.mainTel) {
            node = { obj };
            node.deviceTel = obj.mainTel;
            node.deviceType = obj.mainTelType;
            node.id = obj.operatorID;
            node.parentID = pid;
            node.label = obj.realName;
            node.type = 'operator';
            commit('GetNid', node);
            node.parentName = pNode.label;
            pNode.children.push(node);
          }
          if (obj.viceTel) {
            let node = { obj };
            node.deviceTel = obj.viceTel;
            node.deviceType = obj.viceTelType;
            node.id = obj.operatorID;
            node.parentID = pid;
            node.parentName = pNode.label;
            node.label = obj.realName;
            node.type = 'operator';
            commit('GetNid', node);
            pNode.children.push(node);
          }
        }
        // 职员
        let faxTelMap = (state.faxTelMap = new Map());
        for (let i = 0; i < employees.length; i++) {
          let obj = employees[i];
          let pidObjs = obj.group;
          for (const pidObj of pidObjs) {
            pid = pidObj.groupID;
            pNode = groupMap.get(pid);
            if (!pNode) continue;
            for (const telObj of obj.device) {
              if (telObj.deviceTel) {
                node = { obj };
                node.id = obj.employeeID;
                node.parentID = pid;
                node.label = obj.realName;
                node.type = 'employee';
                node.deviceTel = telObj.deviceTel;
                node.deviceType = telObj.deviceType;
                node.parentName = pNode.label;
                commit('GetNid', node);
                pNode.children.push(node);

                // 传真
                if (telObj.deviceType === 'fax') {
                  let faxNode = faxMap.get(pid);
                  if (faxNode) {
                    faxNode.children.push(node);
                  }
                  faxTelMap.set(telObj.deviceTel, obj);
                }
              }
            }
          }
        }
        state.userTreeDataToDepart = [...treeMap.values()];
        // state.faxTelTreeData = [...faxTreeMap.values()];
        dispatch('filterFax', faxTreeMap);
      } else state.userTreeDataToDepart = [];
    },
    filterFax({ dispatch, commit, state }, faxTreeMap) {
      const filter = children => {
        for (let i = children.length - 1; i >= 0; i--) {
          const item = children[i];
          if (item.type === 'group') {
            if (item.children.length > 0) filter(item.children);
            if (item.children.length === 0) children.splice(i, 1);
          }
        }
      };
      for (const key of faxTreeMap.keys()) {
        let node = faxTreeMap.get(key);
        if (node.children.length > 0) filter(node.children);
        if (node.children.length === 0) faxTreeMap.delete(key);
      }
      state.faxTelTreeData = [...faxTreeMap.values()];
    },
    initBindingVideo({ dispatch, commit, state }, { operators, employees }) {
      let bindingVideoMap = new Map();
      operators.forEach(oper => {
        if (oper.videoID && oper.videoID.length > 0) {
          oper.videoID.forEach(id => {
            let users;
            if ((users = bindingVideoMap.get(id))) {
              users.push(oper);
            } else {
              bindingVideoMap.set(id, [oper]);
            }
          });
        }
      });
      employees.forEach(emp => {
        if (emp.videoID && emp.videoID.length > 0) {
          emp.videoID.forEach(id => {
            let users;
            if ((users = bindingVideoMap.get(id))) {
              users.push(emp);
            } else {
              bindingVideoMap.set(id, [emp]);
            }
          });
        }
      });
      state.bindingVideoMap = bindingVideoMap;
    },
    initUserMeeting({ dispatch, commit, state }) {
      let telMeetingMap = (state.telMeetingMap = new Map());
      SDK.getMeetingList().then(res => {
        let meetingList = res.meet_list.filter(
          item => item.meetMode !== 'monitor'
        );
        meetingList.forEach(e => {
          SDK.getMeetingMember(e.meetID).then(result => {
            let member = result.meet_list;
            member.forEach(g => {
              telMeetingMap.set(g.activeDevice, e.meetID);
            });
          });
        });
      });
    },
    initSupplies({ dispatch, commit, state }) {
      if (sessionStorage.getItem('menuList')) {
        let menuList = JSON.parse(sessionStorage.getItem('menuList'));
        for (let i = 0; i < menuList.length; i++) {
          let item = menuList[i];
          if (item.LoadParameter == '1') {
            // 事件
            if (item.LoadPath === '/myevent') {
              state.hasEventModule = true;
              let eventMap = new Map();

              let types = [
                { eventType: 4, typeName: '特别严重' },
                { eventType: 3, typeName: '较严重' },
                { eventType: 2, typeName: '严重' },
                { eventType: 1, typeName: '一般' },
              ];

              eventPage({ size: 999, current: 1, type: 1 })
                .then(res => {
                  if (res.code === 0) {
                    let eventList = res.data.records;

                    let treeMap = new Map();
                    let node, pNode;

                    types.forEach(item => {
                      node = { obj: item };
                      commit('GetNid', node);
                      node.label = item.typeName;
                      node.type = 'eventgroup';
                      node.isLeaf = false;
                      node.id = item.eventType;
                      node.parentID = '';
                      node.children = [];

                      treeMap.set(item.eventType, node);
                      commit('SetId2Nid', node);
                    });

                    eventList.forEach(item => {
                      pNode = treeMap.get(item.eventType);
                      if (pNode) {
                        item.pos_x = item.eventLongitude || '';
                        item.pos_y = item.eventLatitude || '';
                        item.type = 'event';
                        node = { obj: item };
                        commit('GetNid', node);
                        node.label = item.eventName;
                        node.type = 'event';
                        node.id = item.eventId;
                        node.parentID = item.eventType;
                        node.isLeaf = true;

                        pNode.children.push(node);
                        commit('SetId2Nid', node);

                        eventMap.set(item.eventId, item);
                      }
                    });
                    state.eventTypeMap = treeMap;
                    state.eventTreeData = [...treeMap.values()];
                    state.eventList = eventList;
                    state.eventMap = eventMap;
                  } else {
                    console.log('获取事件失败');
                  }
                })
                .catch(err => {
                  console.log('获取事件失败');
                  state.eventTypeMap = new Map();
                });
            } else if (item.LoadPath.includes('/materials_web')) {
              //
              if (state.hasSuppliesModule) continue;
              // 物资
              state.hasSuppliesModule = true;
              axios
                .all([
                  suppliesTypePage({ size: 999, current: 1 }),
                  suppliesPage({ size: 999, current: 1 }),
                ])
                .then(
                  axios.spread((typeRes, supRes) => {
                    let types = typeRes.records;
                    let suppliesList = supRes.records;

                    let suppliesTypeMap = (state.suppliesTypeMap = new Map());
                    let suppliesMap = new Map();
                    let associatedMap = (state.associatedMap = new Map());

                    let treeMap = new Map();
                    let node, pNode;
                    // 类型
                    types.forEach(item => {
                      node = { obj: item };
                      commit('GetNid', node);
                      node.label = item.typeName;
                      node.type = 'suppliesgroup';
                      node.isLeaf = false;
                      node.id = item.typeId;
                      node.parentID = '';
                      node.children = [];
                      if (item.typeNum !== 'sensor') {
                        treeMap.set(item.typeId, node);
                        commit('SetId2Nid', node);
                      }
                      suppliesTypeMap.set(item.typeId, node);
                    });

                    // 物资
                    let props;
                    suppliesList.forEach(item => {
                      pNode = suppliesTypeMap.get(item.typeId);
                      if (pNode) {
                        props = JSON.parse(item.suppliesProp);
                        if (props) {
                          for (const pro of props) {
                            if (pro.propName === '经度') {
                              item.pos_x = Number(pro.propData) || '';
                            }
                            if (pro.propName === '纬度') {
                              item.pos_y = Number(pro.propData) || '';
                            }
                          }
                        }
                        if (
                          !Object.prototype.hasOwnProperty.call(item, 'pos_x')
                        )
                          item.pos_x = '';
                        if (
                          !Object.prototype.hasOwnProperty.call(item, 'pos_x')
                        )
                          item.pos_y = '';

                        item.type = pNode.obj.typeNum;

                        suppliesMap.set(item.suppliesId, item);
                        // 关联设备
                        if (item.reSuppliesId) {
                          associatedMap.set(item.reSuppliesId, item);
                          return;
                        }

                        node = { obj: item };
                        commit('GetNid', node);
                        node.label = item.suppliesName;
                        node.type = pNode.obj.typeNum;
                        node.id = item.suppliesId;
                        node.parentID = item.typeId;
                        node.isLeaf = true;

                        pNode.children.push(node);
                        commit('SetId2Nid', node);
                      }
                    });

                    state.suppliesTreeData = [...treeMap.values()];
                    state.suppliesTypeList = types;
                    state.suppliesList = suppliesList;
                    state.suppliesMap = suppliesMap;
                  })
                );
            } else if (item.LoadPath.includes('/warning')) {
              //
              if (state.hasWarningModule) continue;
              // 物资
              state.hasWarningModule = true;
              axios.all([getAreaList(), getEquipmentList()]).then(
                axios.spread((areaRes, equRes) => {
                  // console.log('getAreaTree', JSON.stringify(areaRes.data));
                  // console.log('getEquipmentList', JSON.stringify(equRes.data));
                  let arealist = areaRes.data;
                  let equipmentList = equRes.data;

                  let warningAreaMap = (state.warningAreaMap = new Map());
                  let warningEquipmentMap = (state.warningEquipmentMap = new Map());
                  let warningEquipmentPartMap = new Map();
                  // 区域
                  //排序
                  arealist.sort(compare('sortNo'));
                  arealist.forEach(item => {
                    let node = { obj: item };
                    commit('GetNid', node);
                    node.label = item.areaName;
                    node.type = 'warningarea';
                    node.isLeaf = false;
                    node.id = item.areaId;
                    node.parentID = item.parentId;
                    node.children = [];
                    warningAreaMap.set(item.areaId, node);
                    commit('SetId2Nid', node);
                  });

                  // 树结构
                  let treeMap = new Map();
                  for (let key of warningAreaMap.keys()) {
                    let node = warningAreaMap.get(key);
                    let pid = node.parentID;
                    if (!pid && !treeMap.has(pid)) {
                      treeMap.set(key, node);
                    } else if (pid) {
                      let pNode = warningAreaMap.get(pid);
                      if (pNode) pNode.children.push(node);
                    }
                  }

                  if (equipmentList && equipmentList.length > 0) {
                    const length = equipmentList.length;
                    equipmentList.forEach(async (item, index) => {
                      let node = { obj: item };
                      commit('GetNid', node);
                      node.label = item.equipmentName;
                      node.type = 'warningequipment';
                      node.isLeaf = false;
                      node.id = item.equipmentId;
                      node.parentID = item.areaId;
                      node.children = [];
                      try {
                        await getPartList(item.equipmentId).then(res => {
                          let partList = res.data;
                          let part;
                          partList.forEach(i => {
                            i.pos_x = i.longitude || '';
                            i.pos_y = i.latitude || '';
                            i.equipmentName = node.label;
                            part = { obj: i };
                            commit('GetNid', part);
                            part.label = i.partName;
                            part.type = 'warning';
                            part.isLeaf = true;
                            part.id = i.partId;
                            part.parentID = i.equipmentId;
                            node.children.push(part);

                            warningEquipmentPartMap.set(i.partId, i);
                          });
                        });
                        // 由于获取通道是异步的 会导致watch监听不到Map里面值的改变，所以获取完成后再赋值
                        if (index === length - 1) {
                          state.warningEquipmentPartMap = warningEquipmentPartMap;
                        }
                      } catch (error) {
                        console.error('获取告警设备通道失败', error);
                      }
                      let pNode = warningAreaMap.get(item.areaId);
                      if (pNode) {
                        pNode.children.push(node);
                        commit('SetId2Nid', node);
                      }
                      warningEquipmentMap.set(item.equipmentId, item);
                    });
                  }
                  state.warningTreeData = [...treeMap.values()];
                })
              );
            }
          }
        }
        if (
          state.hasSuppliesModule ||
          state.hasEventModule ||
          state.hasWarningModule
        ) {
          dispatch('initWebsocket');
        }
      }
    },
    /*
     *初始化websocket
     *@param type 类型（event,warning，supplies等,有该参数仅接收本类型的上报，不传为b/s接受所有上报）
     */
    initWebsocket({ dispatch, commit, state }, type) {
      // if (!state.hasSuppliesModule) return;
      const protocol = location.protocol == 'http:' ? 'ws://' : 'wss://'; // websocket协议
      const host =
        process.env.NODE_ENV === 'production'
          ? location.host
          : // : '192.168.10.144:12345'; // 服务地址
          '192.168.3.12:8900';
      // '192.168.3.12:8900';
      let timestamp = new Date().getTime();
      let websocketName =
        type == undefined || type == '' ? timestamp : type + '-' + timestamp;
      // let url = `${protocol}${host}/materials/websocket/testname`;
      let url = `${protocol}${host}/materials/websocket/` + websocketName;
      // 创建websocket连接
      if (!state.websocketClient) {
        let websocket = (state.websocketClient = new ReconnectingWebSocket(
          url
        ));

        window.onbeforeunload = () => {
          websocket.close();
          if (state.websocketTimer) {
            clearInterval(state.websocketTimer);
            state.websocketTimer = null;
            console.log('onbeforeunload');
          }
        };

        // 监听打开
        websocket.onopen = msg => console.log('onopen', msg);
        // 监听关闭
        websocket.onclose = msg => {
          state.websocketClient = null;
          websocket.close();
          if (state.websocketTimer) {
            clearInterval(state.websocketTimer);
            state.websocketTimer = null;
          }
        };
        //监听异常
        websocket.onerror = msg => {
          state.websocketClient = null;
          websocket.close();
          if (state.websocketTimer) {
            clearInterval(state.websocketTimer);
            state.websocketTimer = null;
          }
        };
        //监听服务器发送的消息
        websocket.onmessage = msg => {
          if (state.websocketTimer) {
            clearInterval(state.websocketTimer);
            state.websocketTimer = null;
          }
          state.websocketTimer = setInterval(() => {
            console.error('websocketClient 心跳');
            websocket.send('心跳');
          }, 30000);
          console.log('onmessage-----------', msg);
          //登录类型，判断是否是嵌入c/s客户端
          const loginType = sessionStorage.getItem('loginType');
          loginType === 'idispatch'
            ? dispatch('handleMsgByIdispatch', msg)
            : dispatch('handleMsg', msg);
        };
      }
    },
    handleMsg({ dispatch, commit, state, rootGetters }, msg) {
      const rev = JSON.parse(msg.data);
      //告警管理事件
      if (rev.source == 'warning') {
        let data = rev.data;
        if (rev.type == 'warning') {
          dispatch('handleDealWarningInfo', rev);
        } else if (rev.type == 'openVideo') {
          dispatch('handleDealWarningOpenVideo', data);
        }
      } else if (rev.source == 'event') {
        commit('updateEvent', {
          data: rev,
          eventTypeOptions: rootGetters.dict.eventTypeOptions,
        });
        // 事件
        // if (rev.type == 'add') {
        //   //事件新增

        // } else if (rev.type == 'update') {
        //   //事件修改
        // }
      } else {
        // 物资
        commit('updateSupplies', {
          suppliesId: rev.suppliesId,
          data: rev,
        });
      }
      // console.log('handleMsg', JSON.stringify(rev));
    },
    handleMsgByIdispatch({ dispatch, commit, state, rootGetters }, msg) {
      const rev = JSON.parse(msg.data);
      let dataString = msg.data;
      let data = rev.data;
      //告警管理事件
      if (rev.source == 'warning') {
        let data = rev.data;
        let newData;
        if (rev.type == 'warning') {
          newData = {
            equipmentName: data.equipmentName,
            latitude: data.latitude,
            longitude: data.longitude,
            partName: data.partName,
            videoId: '',
            isOver: data.isOver,
            equipmentId: data.equipmentName,
            partId: data.partId,
            // equipmentName: '222',
            // latitude: '222',
            // longitude: '222',
            // partName: '222',
            // videoId: '',
          };
        } else if (rev.type == 'openVideo') {
          let equipment = data.equipment;
          let equipmentPart = data.equipmentPart;
          newData = {
            equipmentName: equipment.equipmentName,
            latitude: equipmentPart.latitude,
            longitude: equipmentPart.longitude,
            partName: equipmentPart.partName,
            videoId: data.videoId,
            isOver: data.isOver,
            // equipmentName: 'test',
            // latitude: '1223',
            // longitude: '2232',
            // partName: '通道一',
            // videoId: '48232548a3515be1a285aae0f0f352d9',
          };
        }
        rev.data = newData;
        // Message("msg")
        dataString = JSON.stringify(rev);
        window.external.WebAlarmEvent(dataString); //接受Stirng类型的json字符串
      } else if (rev.source == 'event') {
        if (rev.type == 'add') {
          window.external.WebAlarmEvent(dataString);
        } else if (rev.type == 'update') {
          window.external.WebAlarmEvent(dataString);
        }
      } else {
      }
    },
    //初始化<本地摘挂机信号>webSocket
    initLocalWebSocket({ dispatch, commit, state }) {
      state.localWebSocketFlag = false;
      // const protocol = 'ws://'; // websocket协议
      // const host =
      //   process.env.NODE_ENV === 'production'
      //     ? '127.0.0.1:12346'
      //     : '10.20.60.60:12346'; // 服务地址
      // let url = `${protocol}${host}`;
      let url = 'ws://127.0.0.1:12346';
      // let url = 'ws://192.168.3.145:12346';
      //判断浏览器系统,windows不连接小调度台
      var sUserAgent = navigator.userAgent.toLowerCase().match('windows');
      if (sUserAgent) {
        return;
      }
      //根据readyState属性可以判断webSocket的连接状态，该属性的值可以是下面几种：
      // 0 ：对应常量CONNECTING (numeric value 0)，正在建立连接连接，还没有完成。
      // 1 ：对应常量OPEN (numeric value 1)，连接成功建立，可以进行通信。
      // 2 ：对应常量CLOSING (numeric value 2)连接正在进行关闭握手，
      // 3 : 对应常量CLOSED (numeric value 3) 连接已经关闭或者根本没有建立。
      if (
        !state.websocketLocalClient ||
        state.websocketLocalClient.readyState != 1
      ) {
        let websocket = (state.websocketLocalClient = new WebSocket(url));
        // 监听打开
        websocket.onopen = msg => {
          console.log('话务台onopen', msg);
          state.localWebSocketFlag = true;
        };
        // 监听关闭
        websocket.onclose = msg => {
          state.localWebSocketFlag = false;
          // console.log('话务台onclose', msg);
          if (lockReconnect || lockReconnectNum > 6) return;
          lockReconnect = true;
          //没连接上会一直重连，设置延迟避免请求过多
          setTimeout(function () {
            dispatch('initLocalWebSocket');
            lockReconnect = false;
            lockReconnectNum++;
          }, 2000);
        };
        //监听异常
        websocket.onerror = msg => {
          state.localWebSocketFlag = false;
          // console.log('话务台error', msg);
          if (lockReconnect || lockReconnectNum > 6) return;
          lockReconnect = true;
          setTimeout(function () {
            dispatch('initLocalWebSocket');
            lockReconnect = false;
            lockReconnectNum++;
          }, 2000);
        };
        //监听服务器发送的消息
        websocket.onmessage = msg => {
          // console.log('话务台onmessage', msg.data);
          if (msg.data == 'on' || msg.data == 'off') {
            state.localPhoneStatus = msg.data;
            if (msg.data == 'on') {
              //手柄拿起，默认按钮变回听筒
              state.localButtonStatus = 'jyoff';
            }
          } else {
            state.localButtonStatus = msg.data;
          }
          window.handleLocalAccept(msg.data);
        };
      }
    },

    // 更新摄像头数据
    updateVideo({ dispatch, commit, state }, obj) { },

    cacheEvent({ dispatch, commit, state }, e) {
      switch (e.type) {
        case 'LinkVideoClose':
          commit('LinkVideoClose', e);
          break;
        case 'UserStatus':
          handleUserStatus(state, e);
          break;
        case 'fenceAlarm':
          handleFenceAlarm(state, e);
          break;
        case 'VideoInfoMod':
          if (e.result === 'succ') {
            console.log('cacheEvent', e.type, JSON.stringify(e));
          }
          break;
        case 'EmployeeMod':
        case 'OperatorMod':
          if (e.result === 'succ') {
            console.log('cacheEvent', e.type, JSON.stringify(e));
          }
          break;
        case 'meet_member_event':
          //会议成员处理
          if (e.event == 'DelMeetMember') {
            state.deviceStatusMap.delete(e.user, e.meetID);
          } else if (e.event == 'NewMeetMember') {
            state.telMeetingMap.set(e.user, e.meetID);
          }
          break;
      }
    },
    //菜单事件
    navEvent({ dispatch, commit, state }) {
      state.navKey = state.navKey + 1;
    },
    //告警上报处理
    handleDealWarningInfo({ dispatch }, rev) {
      let data = rev.data;
      window.handleCreatWarningNotification(data);
      let menuList = JSON.parse(sessionStorage.getItem('menuList'));
      menuList.forEach(element => {
        if (element.LoadPath == '/warning') {
          element.newInfoCount = element.newInfoCount + 1;
        }
      });
      sessionStorage.setItem('menuList', JSON.stringify(menuList));
      dispatch('navEvent'); // vuex缓存

      if (!state.warningAreaMap || state.warningAreaMap.size === 0) {
        console.log('数据未加载完成');
        return;
      }
      if (!state.warningEquipmentMap || state.warningEquipmentMap.size === 0) {
        console.log('数据未加载完成');
        return;
      }
      if (
        !state.warningEquipmentPartMap ||
        state.warningEquipmentPartMap.size === 0
      ) {
        console.log('数据未加载完成');
        return;
      }
      if (!state.warningEquipmentPartMap.get(rev.data.partId)) {
        console.log('cache 没有通道');
        return;
      }
      if (state.websocketCallback) {
        rev.data.pos_x = rev.data.longitude || '';
        rev.data.pos_y = rev.data.latitude || '';
        rev.data.videoId = state.warningEquipmentPartMap.get(
          rev.data.partId
        ).videoId;
        state.websocketCallback(rev);
      }
    },

    //告警打开摄像头事情
    handleDealWarningOpenVideo({ dispatch }, data) {
      window.handleCreatWarningOpenvideoNotification(data);
    },
  },
};

// 处理用户状态
const handleUserStatus = (state, e) => {
  state.deviceStatusMap.set(e.deviceTel, e.deviceStatus);
  // console.log('处理用户状态', JSON.stringify(e));
  let user =
    state.telOperatorMap.get(e.deviceTel) ||
    state.telEmployeeMap.get(e.deviceTel);
  if (user) user.status = e.deviceStatus;
  //记录用户间呼叫关系
  state.deviceLinkMap.set(e.deviceTel, e.linkDevice)
};

// 处理电子围栏告警
const handleFenceAlarm = (state, e) => {
  Message({
    showClose: true,
    message: '电子围栏告警',
    type: 'success',
    duration: 3000,
  });
  // let noti = state.fenceAlarmMap.get();
  let noti = Notification({
    title: '告警',
    showClose: true,
    type: 'warning',
    customClass: 'custom-warning-notification',
    message: `时间${parseStr2Date(e.alarmTime)}，人员“${e.userName
      }”闯入电子围栏(${e.fenceName})，请注意查看`,
    duration: 0,
  });
};

export default cache;

// 对数据进行过滤
function fiterUserGroupTreeData(data) {
  const convert = arr => {
    const newArr = arr.filter(
      item =>
        item.obj.groupType !== 'clustergroup' &&
        item.obj.groupType !== 'dynamicgroup'
    );
    return newArr.map(item => {
      if (item.children) {
        item.children = convert(item.children);
      }
      return item;
    });
  };
  return convert(data);
}
